package com.spring.nio.core.listener;

import com.spring.nio.common.BasicConstant;
import com.spring.nio.core.BasicServer;
import com.spring.nio.core.context.NioServerContext;
import com.spring.nio.core.http.HttpRunnable;
import com.spring.nio.pool.WorkerThreadPool;
import com.spring.nio.util.LocalTime;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.time.LocalDateTime;
import java.util.Optional;

/**
 * @author: YSFY
 * @date: 2021-02-21 09:42
 * @pacage_name: com.spring.nio.core.listener
 * @class_name: ClientServerListenerRunnable
 * @description: client端监听线程
 */

@Slf4j
public class HttpServerListenerRunnable implements Runnable {
    private int httpPort = 0;
    private String address = "";
    private ServerSocketChannel serverSocketChannel;
    public HttpServerListenerRunnable() {
        this.httpPort = Integer.valueOf(BasicServer.getMap().get(BasicConstant.NIO_HTTP_PORT).toString());
        this.address = String.valueOf(BasicServer.getMap().get(BasicConstant.SERVER_IP));
    }

    @Override
    public void run() {
        try {
            this.initServerSocketChannel();

            this.beginListener();
        } catch (Exception e) {
            log.error("[" + LocalTime.formatDate(LocalDateTime.now()) + "] ClientServerListenerRunnable | --> 文件客户端Http监听服务线程异常, error = {}", e.getMessage());
        }
    }

    private void initServerSocketChannel() throws IOException {
        this.serverSocketChannel = ServerSocketChannel.open();
        this.serverSocketChannel.bind(new InetSocketAddress(InetAddress.getByName(address), this.httpPort));
        serverSocketChannel.configureBlocking(true);

        log.info("[" + Thread.currentThread().getName() + " ] ClientServerListenerRunnable | --> 文件http客户端服务监听成功, 开始等待客户端连接, 监听地址 = [{}], thread = [{}]", (this.address + ":" + this.httpPort), Thread.currentThread().getName());
    }

    private void beginListener() {
        if(!this.serverSocketChannel.isOpen()) {
            throw new RuntimeException("ServerSocketChannel is not open or registered");
        }

        SocketChannel socketChannel = null;
        while (true) {
            try {
                socketChannel = serverSocketChannel.accept();
                if(Optional.ofNullable(socketChannel).isPresent()) {
                    socketChannel.configureBlocking(false);
                    WorkerThreadPool.executorService.submit(new HttpRunnable(socketChannel));
                }
            } catch (IOException e) {
                log.error("[" + LocalTime.formatDate(LocalDateTime.now()) + "] ClientServerListenerRunnable | --> 文件Http客户端处理连接异常,将直接关闭连接, 客户端地址 = [{}], error = [{}]", NioServerContext.getRemoteAddress(socketChannel), e.getMessage());
                NioServerContext.closedAndRelease(socketChannel);
            }
        }
    }
}
